using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Algorithms;
using System;

namespace UI
{
	using PointType = Form1.PointClass;
	using System.IO;

	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		public void InitializeGraph()
		{
			Kruskal<PointType> kruskal = new Kruskal<PointType>();

			foreach (PointType p in points)
			{
				kruskal.AddNode(p);
			}

			for (int i = 0; i < points.Count - 1; i++)
			{
				for (int j = i + 1; j < points.Count; j++)
				{
					kruskal.AddEdge(points[i], points[j], Dist(i, j));
				}
			}

			edges = kruskal.ComputeMinimalSpanningTree();
		}

		private IEnumerable<Edge<PointType>> edges;

		public float Dist(int i, int j)
		{
			int x = points[i].X - points[j].X;
			int y = points[i].Y - points[j].Y;
			return (float)Math.Sqrt(x * x + y * y);
		}

		public class PointClass
		{
			public PointClass(int x, int y)
			{
				X = x;
				Y = y;
			}
			public int X;
			public int Y;
		}

		private List<PointType> points = new List<PointType>();

		private void DrawEdge(Graphics g, Edge<PointType> e)
		{
			g.DrawLine(Pens.LightBlue, e.Start.X, e.Start.Y, e.End.X, e.End.Y);
		}

		private void DrawPoint(Graphics g, PointType p)
		{
			const int pointSize = 4;
			g.FillEllipse(Brushes.LavenderBlush,
				p.X - pointSize,
				p.Y - pointSize,
				2 * pointSize + 1,
				2 * pointSize + 1);
		}

		PointType drag = null;

		private void canvas1_MouseDown(object sender, MouseEventArgs e)
		{
			drag = FindPoint(e.X, e.Y);
			if (drag != null)
			{
				return;
			}

			points.Add(new PointType(e.X, e.Y));
			InitializeGraph();
			canvas1.Refresh();
		}

		private PointType FindPoint(int x, int y)
		{
			foreach (PointType p in points)
			{
				if (Math.Abs(p.X - x) + Math.Abs(p.Y - y) < 8)
				{
					return p;
				}
			}
			return null;
		}

		private void canvas1_Paint(object sender, PaintEventArgs e)
		{
			e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
			if (points == null || edges == null)
			{
				return;
			}

			e.Graphics.Clear(Color.White);

			foreach (PointType p in points)
			{
				DrawPoint(e.Graphics, p);
			}

			foreach (Edge<PointType> edge in edges)
			{
				DrawEdge(e.Graphics, edge);
			}
		}

		private void canvas1_MouseMove(object sender, MouseEventArgs e)
		{
			if (drag != null && e.Button == MouseButtons.Left)
			{
				drag.X = e.X;
				drag.Y = e.Y;
				InitializeGraph();
				canvas1.Refresh();
			}
		}

		private void canvas1_Load(object sender, EventArgs e)
		{
			this.Cursor = new Cursor(this.GetType(), "3dsmove.cur");
			//using (MemoryStream m = new MemoryStream(Properties.Resources._3dsmove))
			//{
			//    this.Cursor = new Cursor(m);
			//}
		}
	}
}